// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#pragma once

#include <vector>

namespace kumo::pollux::dwrf::utils {
// Assumptions:
// 1) all raw byte buffers are added at the beginning.
//    If a raw byte buffer is added mid flight, we'll start iterating
//    at the same bit offset as all others.
// 2) caller is responsible for passing in byte buffers that are
//    big enough. This class doesn't do any boundary checking.
template <typename T>
class BulkBitIterator {
  static constexpr uint8_t kWidth = sizeof(T) * 8;

 public:
  explicit BulkBitIterator() : mod_{0}, index_{0} {}

  void addRawByteBuffer(T* buf) {
    rawByteBuffers_.push_back(buf);
    byteCaches_.push_back(0);
  }

  // Caller needs to always call loadNext() before accessing
  // value.
  void loadNext() {
    if (mod_ == 0) {
      // Refresh the byte caches.
      for (size_t i = 0; i < rawByteBuffers_.size(); ++i) {
        byteCaches_[i] = rawByteBuffers_[i][index_];
      }
      ++index_;
    }
    mask_ = static_cast<T>(1) << mod_;
    // This is actually mod_ for the next value. We do this
    // so that loadNext() would not try to load something out
    // of range.
    mod_ = (mod_ + 1) % kWidth;
  }

  bool hasValueAt(size_t index) {
    return byteCaches_[index] & mask_;
  }

 private:
  uint8_t mod_;
  int32_t index_;
  std::vector<T*> rawByteBuffers_;
  std::vector<T> byteCaches_;
  T mask_;
};

} // namespace kumo::pollux::dwrf::utils
